﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Minio.DataModel.Args;
using Minio;
using Minio.Exceptions;
using Minio.DataModel;
using System.IO;
using System.Net.Mime;
using System.Reactive.Linq;

namespace Demo.Net.API.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class MinioController : ControllerBase
    {

        private readonly IMinioClient _minioClient;

        public MinioController(IMinioClient minioClient)
        {
            _minioClient = minioClient;
        }


        [HttpGet]
        [ProducesResponseType(typeof(string), StatusCodes.Status200OK)]
        public async Task<IActionResult> GetUrl(string bucketID)
        {
            return Ok(await _minioClient.PresignedGetObjectAsync(new PresignedGetObjectArgs()
                    .WithBucket(bucketID))
                .ConfigureAwait(false));
        }

        [HttpPost]
        public async Task<IActionResult> UploadFile(IFormFile file)
        {
            if (file == null || file.Length == 0)
            {
                return BadRequest("No file uploaded.");
            }

            var bucketName = "test";
            var objectName = DateTime.Now.ToString("yyyy-MM-dd")+"/"+ file.FileName;
            var contentType = file.ContentType;

            if (string.IsNullOrEmpty(objectName))
            {
                return BadRequest("File name is required.");
            }

            try
            {
                // Check if the bucket exists, and create it if it doesn't
                var beArgs = new BucketExistsArgs()
                    .WithBucket(bucketName);
                bool found = await _minioClient.BucketExistsAsync(beArgs).ConfigureAwait(false);
                if (!found)
                {
                    var mbArgs = new MakeBucketArgs()
                        .WithBucket(bucketName);
                    await _minioClient.MakeBucketAsync(mbArgs).ConfigureAwait(false);
                }

                using (var stream = file.OpenReadStream())
                {
                    // Upload the file to the bucket
                    var putObjectArgs = new PutObjectArgs()
                        .WithBucket(bucketName)
                        .WithObject(objectName)
                        .WithStreamData(stream)
                        .WithObjectSize(stream.Length)
                        .WithContentType(contentType);

                  var putresult =   await _minioClient.PutObjectAsync(putObjectArgs).ConfigureAwait(false);
                }

                return Ok($"Successfully uploaded {objectName}");
            }
            catch (MinioException e)
            {
                return StatusCode(500, $"File Upload Error: {e.Message}");
            }
        }


        [HttpPost]
        public async Task<IActionResult> DownLoadFile(string fileName)
        {

            using (MemoryStream memoryStream = new MemoryStream())
            {
                var getObjTagsArg = new GetObjectArgs()
                                        .WithBucket("test")
                                        .WithObject(fileName)
                                        .WithCallbackStream((stream) =>
                                        {
                                            stream.CopyTo(memoryStream);
                                        });
                memoryStream.Position = 0;
                try
                {
                    var target = await _minioClient.GetObjectAsync(getObjTagsArg);
                    byte[] b = memoryStream.ToArray();
                    return File(b,target.ContentType,fileName);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
            return Ok();
        }


        [HttpGet]
        public async Task<IActionResult> ListObjects()
        {
            var listObjectsArgs = new ListObjectsArgs()
                .WithBucket("test");

            var objects =  _minioClient.ListObjectsAsync(listObjectsArgs).ToList();

            return Ok(objects);
        }

        [HttpGet]
        public async Task<string> GetPresignedUrlAsync(string fileName)
        {
            try
            {
                // 生成预签名 URL
                string presignedUrl = await _minioClient.PresignedGetObjectAsync(new PresignedGetObjectArgs().WithBucket("test").WithObject(fileName).WithExpiry(86400));

                return presignedUrl;
            }
            catch (MinioException ex)
            {
                Console.WriteLine($"Error occurred: {ex.Message}");
                throw;
            }
        }

        [HttpGet]
        public async Task<IActionResult> DeleteFile(string fileName)
        {
           await  _minioClient.RemoveObjectAsync(new RemoveObjectArgs().WithBucket("test").WithObject(fileName));
            return Ok();
         }
    }
}
